<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>API测试工具 - 考研预测系统</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: '#3B82F6',
            secondary: '#10B981',
            danger: '#EF4444',
            neutral: '#64748B',
          }
        }
      }
    }
  </script>
  <style type="text/tailwindcss">
    @layer utilities {
      .content-auto {
        content-visibility: auto;
      }
      .api-card {
        @apply bg-white rounded-lg shadow-md p-4 mb-4 transition-all duration-300 hover:shadow-lg;
      }
      .btn {
        @apply px-4 py-2 rounded-md font-medium transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2;
      }
      .btn-primary {
        @apply bg-primary text-white hover:bg-primary/90 focus:ring-primary/50;
      }
      .btn-secondary {
        @apply bg-secondary text-white hover:bg-secondary/90 focus:ring-secondary/50;
      }
      .btn-danger {
        @apply bg-danger text-white hover:bg-danger/90 focus:ring-danger/50;
      }
      .input-field {
        @apply w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary;
      }
    }
  </style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-6xl">
  <header class="mb-8 text-center">
    <h1 class="text-3xl font-bold text-gray-800 mb-2">API测试工具</h1>
    <p class="text-neutral">测试 localhost:8080/api/v1 下的接口功能</p>
  </header>

  <!-- 健康检查 -->
  <div class="api-card">
    <h2 class="text-xl font-semibold mb-3 flex items-center">
      <i class="fa fa-heartbeat text-primary mr-2"></i>健康检查
    </h2>
    <p class="text-gray-600 mb-3">检查服务及外部API连接状态</p>
    <button id="healthCheckBtn" class="btn btn-primary">
      <i class="fa fa-check mr-1"></i> 执行健康检查
    </button>
    <div id="healthCheckResult" class="mt-3 p-3 rounded-md hidden"></div>
  </div>

  <!-- 请求参数表单 -->
  <div class="api-card">
    <h2 class="text-xl font-semibold mb-4 flex items-center">
      <i class="fa fa-pencil-square-o text-primary mr-2"></i>请求参数
    </h2>
    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">学生ID (student_id)</label>
        <input type="text" id="studentId" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">姓名 (name)</label>
        <input type="text" id="name" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">GPA (gpa)</label>
        <input type="number" id="gpa" step="0.01" min="0" max="4" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">英语四级 (cet4)</label>
        <input type="number" id="cet4" min="0" max="710" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">高等数学（上）(math1)</label>
        <input type="number" id="math1" step="0.1" min="0" max="100" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">高等数学（下）(math2)</label>
        <input type="number" id="math2" step="0.1" min="0" max="100" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">大学英语1 (english1)</label>
        <input type="number" id="english1" step="0.1" min="0" max="100" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">大学英语2 (english2)</label>
        <input type="number" id="english2" step="0.1" min="0" max="100" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">大学英语3 (english3)</label>
        <input type="number" id="english3" step="0.1" min="0" max="100" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">大学英语4 (english4)</label>
        <input type="number" id="english4" step="0.1" min="0" max="100" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">专业 (Major)</label>
        <input type="text" id="major" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">学院 (college)</label>
        <input type="text" id="college" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">目标院校 (TargetSchool)</label>
        <input type="text" id="targetSchool" class="input-field">
      </div>
      <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">相似性阈值 (scoreThreshold)</label>
        <input type="number" id="scoreThreshold" step="0.5" min="0" max="20" value="5.0" class="input-field">
      </div>
    </div>
  </div>

  <!-- API操作区域 -->
  <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
    <!-- 综合查询 -->
    <div class="api-card">
      <h2 class="text-xl font-semibold mb-3 flex items-center">
        <i class="fa fa-search text-primary mr-2"></i>综合查询
      </h2>
      <p class="text-gray-600 mb-3">调用 /students/query 接口</p>
      <button id="queryBtn" class="btn btn-primary">
        <i class="fa fa-search mr-1"></i> 执行查询
      </button>
    </div>

    <!-- 相似学生查询 -->
    <div class="api-card">
      <h2 class="text-xl font-semibold mb-3 flex items-center">
        <i class="fa fa-users text-primary mr-2"></i>相似学生查询
      </h2>
      <p class="text-gray-600 mb-3">调用 /students/similar 接口</p>
      <button id="similarBtn" class="btn btn-primary">
        <i class="fa fa-search mr-1"></i> 查找相似学生
      </button>
    </div>

    <!-- 目标院校学生查询 -->
    <div class="api-card">
      <h2 class="text-xl font-semibold mb-3 flex items-center">
        <i class="fa fa-university text-primary mr-2"></i>目标院校学生
      </h2>
      <p class="text-gray-600 mb-3">调用 /students/target-school 接口</p>
      <button id="targetSchoolBtn" class="btn btn-primary">
        <i class="fa fa-search mr-1"></i> 查找目标院校学生
      </button>
    </div>

    <!-- 导出Excel -->
    <div class="api-card">
      <h2 class="text-xl font-semibold mb-3 flex items-center">
        <i class="fa fa-file-excel-o text-primary mr-2"></i>导出Excel
      </h2>
      <p class="text-gray-600 mb-3">调用 /students/export 接口</p>
      <button id="exportBtn" class="btn btn-secondary">
        <i class="fa fa-download mr-1"></i> 导出Excel
      </button>
    </div>

    <!-- 考研预测 -->
    <div class="api-card">
      <h2 class="text-xl font-semibold mb-3 flex items-center">
        <i class="fa fa-line-chart text-primary mr-2"></i>考研预测
      </h2>
      <p class="text-gray-600 mb-3">调用 /predict 接口</p>
      <button id="predictBtn" class="btn btn-primary">
        <i class="fa fa-calculator mr-1"></i> 执行预测
      </button>
    </div>

    <!-- 外部相似学生 -->
    <div class="api-card">
      <h2 class="text-xl font-semibold mb-3 flex items-center">
        <i class="fa fa-external-link text-primary mr-2"></i>外部相似学生
      </h2>
      <p class="text-gray-600 mb-3">调用 /students/external-similar 接口</p>
      <button id="externalSimilarBtn" class="btn btn-primary">
        <i class="fa fa-search mr-1"></i> 获取外部相似学生
      </button>
    </div>
  </div>

  <!-- 结果展示区域 -->
  <div class="api-card">
    <h2 class="text-xl font-semibold mb-3 flex items-center">
      <i class="fa fa-results text-primary mr-2"></i>响应结果
    </h2>
    <div class="relative">
      <div id="loadingIndicator" class="hidden absolute inset-0 bg-white/80 flex items-center justify-center">
        <div class="flex flex-col items-center">
          <i class="fa fa-spinner fa-spin text-3xl text-primary mb-2"></i>
          <p>处理中...</p>
        </div>
      </div>
      <pre id="responseResult" class="bg-gray-50 p-4 rounded-md border border-gray-200 overflow-auto max-h-96 text-sm"></pre>
    </div>
  </div>
</div>

<script>
  const API_BASE_URL = 'http://localhost:8080/api/v1';
  const responseResult = document.getElementById('responseResult');
  const loadingIndicator = document.getElementById('loadingIndicator');

  // 显示加载状态
  function showLoading() {
    loadingIndicator.classList.remove('hidden');
    responseResult.textContent = '';
  }

  // 隐藏加载状态
  function hideLoading() {
    loadingIndicator.classList.add('hidden');
  }

  // 显示响应结果
  function showResponse(data) {
    responseResult.textContent = JSON.stringify(data, null, 2);
  }

  // 显示错误信息
  function showError(error) {
    responseResult.textContent = `错误: ${error.message || JSON.stringify(error, null, 2)}`;
  }

  // 获取表单数据（通用，包含scoreThreshold）
  function getFormData() {
    return {
      student_id: document.getElementById('studentId').value || '',
      name: document.getElementById('name').value || '',
      gpa: document.getElementById('gpa').value ? parseFloat(document.getElementById('gpa').value) : null,
      cet4: document.getElementById('cet4').value ? parseInt(document.getElementById('cet4').value) : null,
      math1: document.getElementById('math1').value ? parseFloat(document.getElementById('math1').value) : null,
      math2: document.getElementById('math2').value ? parseFloat(document.getElementById('math2').value) : null,
      english1: document.getElementById('english1').value ? parseFloat(document.getElementById('english1').value) : null,
      english2: document.getElementById('english2').value ? parseFloat(document.getElementById('english2').value) : null,
      english3: document.getElementById('english3').value ? parseFloat(document.getElementById('english3').value) : null,
      english4: document.getElementById('english4').value ? parseFloat(document.getElementById('english4').value) : null,
      Major: document.getElementById('major').value || '',
      college: document.getElementById('college').value || '',
      TargetSchool: document.getElementById('targetSchool').value || '',
      scoreThreshold: document.getElementById('scoreThreshold').value ? parseFloat(document.getElementById('scoreThreshold').value) : 5.0
    };
  }

  // 获取预测专用数据（不包含scoreThreshold）
  function getPredictFormData() {
    return {
      student_id: document.getElementById('studentId').value || '',
      name: document.getElementById('name').value || '',
      gpa: document.getElementById('gpa').value ? parseFloat(document.getElementById('gpa').value) : null,
      cet4: document.getElementById('cet4').value ? parseInt(document.getElementById('cet4').value) : null,
      math1: document.getElementById('math1').value ? parseFloat(document.getElementById('math1').value) : null,
      math2: document.getElementById('math2').value ? parseFloat(document.getElementById('math2').value) : null,
      english1: document.getElementById('english1').value ? parseFloat(document.getElementById('english1').value) : null,
      english2: document.getElementById('english2').value ? parseFloat(document.getElementById('english2').value) : null,
      english3: document.getElementById('english3').value ? parseFloat(document.getElementById('english3').value) : null,
      english4: document.getElementById('english4').value ? parseFloat(document.getElementById('english4').value) : null,
      Major: document.getElementById('major').value || '',
      college: document.getElementById('college').value || '',
      TargetSchool: document.getElementById('targetSchool').value || ''
    };
  }

  // 健康检查
  document.getElementById('healthCheckBtn').addEventListener('click', async () => {
    try {
      showLoading();
      const response = await fetch(`${API_BASE_URL}/health`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json'
        }
      });
      const result = await response.json();
      showResponse(result);

      // 显示结果样式
      if (result.code === 200) {
        responseResult.classList.add('bg-green-50', 'border-green-200');
        responseResult.classList.remove('bg-red-50', 'border-red-200');
      } else {
        responseResult.classList.add('bg-red-50', 'border-red-200');
        responseResult.classList.remove('bg-green-50', 'border-green-200');
      }
    } catch (error) {
      showError(error);
      responseResult.classList.add('bg-red-50', 'border-red-200');
      responseResult.classList.remove('bg-green-50', 'border-green-200');
    } finally {
      hideLoading();
    }
  });

  // 综合查询
  document.getElementById('queryBtn').addEventListener('click', async () => {
    const data = getFormData();
    try {
      showLoading();
      const response = await fetch(`${API_BASE_URL}/students/query`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      });
      const result = await response.json();
      showResponse(result);
    } catch (error) {
      showError(error);
    } finally {
      hideLoading();
    }
  });

  // 相似学生查询
  document.getElementById('similarBtn').addEventListener('click', async () => {
    const data = getFormData();
    try {
      showLoading();
      const response = await fetch(`${API_BASE_URL}/students/similar`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      });
      const result = await response.json();
      showResponse(result);
    } catch (error) {
      showError(error);
    } finally {
      hideLoading();
    }
  });

  // 目标院校学生查询
  document.getElementById('targetSchoolBtn').addEventListener('click', async () => {
    const data = getFormData();
    try {
      showLoading();
      const response = await fetch(`${API_BASE_URL}/students/target-school`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      });
      const result = await response.json();
      showResponse(result);
    } catch (error) {
      showError(error);
    } finally {
      hideLoading();
    }
  });

  // 导出Excel
  document.getElementById('exportBtn').addEventListener('click', async () => {
    const data = getFormData();
    try {
      showLoading();
      const response = await fetch(`${API_BASE_URL}/students/export`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const blob = await response.blob();
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = '相似学生信息.xlsx';
      document.body.appendChild(a);
      a.click();
      a.remove();
      window.URL.revokeObjectURL(url);

      showResponse({ success: true, message: 'Excel导出成功' });
    } catch (error) {
      showError(error);
    } finally {
      hideLoading();
    }
  });

  // 考研预测
  document.getElementById('predictBtn').addEventListener('click', async () => {
    const data = getPredictFormData();  // 使用预测专用数据，不包含scoreThreshold
    try {
      showLoading();
      const response = await fetch(`${API_BASE_URL}/predict`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      });
      const result = await response.json();
      showResponse(result);
    } catch (error) {
      showError(error);
    } finally {
      hideLoading();
    }
  });

  // 外部相似学生查询
  document.getElementById('externalSimilarBtn').addEventListener('click', async () => {
    const data = getFormData();
    try {
      showLoading();
      const response = await fetch(`${API_BASE_URL}/students/external-similar`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      });
      const result = await response.json();
      showResponse(result);
    } catch (error) {
      showError(error);
    } finally {
      hideLoading();
    }
  });
</script>
</body>
</html>